import { dayjs } from 'element-plus';

/**
 * @description 辅助函数  对象的合并
 * @param args
 * @return object 合并后的对象
 * */
export const xtend = (...args) => Object.assign({}, ...args);

/**
 * @description 辅助函数  对象的映射
 * @param arr Array 被映射的数组
 * @param object Object 映射的对象
 * @param key string 映射的键
 * @return [] 映射后的对象
 * */
// eslint-disable-next-line no-return-assign
export const objectMap = (arr, object, key) =>
  arr instanceof Array && arr.length
    ? arr.map(el => {
        const flg = el[key];
        el[key] = object[flg] ? object[flg] : `未知`;
        return el;
      })
    : [];
export const objectArrayMap = arr =>
  arr instanceof Array && arr.length
    ? arr.map(el => {
        for (const [key, value] of Object.entries(el)) {
          if (value instanceof Array && value.length) {
            el[`${key}_Name`] = value
              .reduce((pre, cur) => pre.concat(`,${cur.name}`), '')
              .replace(/^,/, '');
          }
        }
        return el;
      })
    : '';

// 将org中的值深拷贝到target中，如果org中不存在该值，则使用target中的默认值
export const setObjectValue = (target, org) => {
  for (const [key, value] of Object.entries(target)) {
    target[key] = org[key] !== undefined ? org[key] : value;
  }
};

/*
 * @des 将data:image,base64图片信息生成文件图片
 *  */
export function dataURLtoFile(dataUrl, fileName) {
  const arr = dataUrl.split(',');
  const mime = arr[0].match(/:(.*?);/)[1];
  // 传统字符转字节，兼容低端web平台
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  // const buffer = Buffer.from(arr[1], 'base64') node平台时替代
  return new File([u8arr], fileName, { type: mime });
}

// 读取文件流创建文件下载链接
export const downloadStream = res => {
  const fileNames = res.headers['content-disposition'];
  if (fileNames) {
    // 解码
    const fileName = decodeURIComponent(fileNames.match(/=(.*)$/)[1]);
    // 处理返回的文件流
    const blob = new Blob([res.data], {
      type: 'application/octet-stream; charset=utf-8',
    });
    if ('download' in document.createElement('a')) {
      // 非IE下载
      const a = document.createElement('a'); // 创建一个a标签
      a.download = fileName; // 指定文件名称
      a.style.display = 'none'; // 页面隐藏
      a.href = URL.createObjectURL(blob); // href用于下载地址
      document.body.appendChild(a); // 插到页面上
      a.click(); // 通过点击触发
      URL.revokeObjectURL(a.href); // 释放URL 对象
      document.body.removeChild(a); // 删掉a标签
    } else {
      // IE10 + 下载
      navigator.msSaveBlob(blob, fileName);
    }
  }
};

export const dateFormat = (date, type = 'YYYY-MM-DD HH:mm:ss') =>
  dayjs(date).format(type);

export const dateIsValid = date => dayjs(date).isValid();

export const typeof_value = obj =>
  Object.prototype.toString.call(obj).slice(8, -1);

/**
 *  @description 格式化返回的数据中包含日期格式
 *  @return  []|object 格式化后的数组或者对象
 * @param obj
 * */
export const formatObject = obj => {
  const timeName = [
    'CreatedAt',
    'UpdatedAt',
    'time',
    'Time',
    'start_time',
    'end_time',
    'startTime',
    'endTime',
  ];
  const map = {
    Array: obj => {
      if (obj.length) {
        obj.map(el => {
          formatObject(el);
        });
      }
    },
    Object: obj => {
      for (const [key, value] of Object.entries(obj)) {
        if (
          dateIsValid(value) &&
          timeName.includes(key) &&
          value !== '0001-01-01T00:00:00Z'
        ) {
          obj[key] = dateFormat(value);
        }
      }
    },
  };
  map[typeof_value(obj)](obj);
  return obj;
};

// 数据返回做映射
export function mapList(arr, obj = { equipment: 'name', icon: 'path' }) {
  if (arr && arr.length) {
    return arr.map(el => {
      for (const [key, value] of Object.entries(el)) {
        if (typeof value === 'object' && value !== null && key in obj) {
          el[key] = value[obj[key]] ? value[obj[key]] : '未知';
        }
      }
      return el;
    });
  }
  return [];
}

export const IP_REGEXP =
  /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/;

//  Ip校验
export const verifyIP = ip => IP_REGEXP.test(ip);

export const categoryMapList = {
  虚拟机: 1,
  容器: 2,
  实物: 3,
  测试集群: 4,
  内置组件: 5,
  沙箱网络: 6,
  本地实物: 7,
  远程实物: 8,
  工具资源: 9,
};

export const protocolList = [
  'arp',
  'icmp',
  'icmp6',
  'ip',
  'ipv6',
  'tcp',
  'tcp6',
  'udp',
  'udp6',
];
export const getUrlParams = function (href, params) {
  var urlObj = {};
  if (!href) {
    return false;
  }
  var urlParams = href;
  var urlArr = urlParams.split('&');
  for (var i = 0; i < urlArr.length; i++) {
    var urlArrItem = urlArr[i].split('=');
    urlObj[urlArrItem[0]] = urlArrItem[1];
  } // 判断是否有参数
  if (arguments.length >= 1) {
    return urlObj[params];
  }
  return urlObj;
};

export const getRandomIP = function (ipWithMask) {
  // 提取 IP 和子网掩码长度
  const [ip, maskBits] = ipWithMask.split('/');
  const mask = parseInt(maskBits, 10);

  // 将 IP 地址转换为整数
  const ipToInt = (ip) => ip.split('.').reduce((acc, octet) => (acc << 8) | parseInt(octet, 10), 0);

  // 将整数转换回 IP 地址
  const intToIp = (int) =>
      [24, 16, 8, 0].map((shift) => (int >> shift) & 255).join('.');

  // 生成子网掩码
  const netmask = (0xffffffff << (32 - mask)) >>> 0;

  // 计算网络地址
  const ipInt = ipToInt(ip);
  const network = ipInt & netmask; // 网络地址
  const broadcast = network | ~netmask; // 广播地址

  // 计算子网的可用 IP 范围
  const startIp = network + 1; // 第一个可用 IP
  const endIp = broadcast - 1; // 最后一个可用 IP

  // 如果子网内只有一个 IP 地址
  if (startIp > endIp) {
    return { givenIp: ip, randomIp: ip }; // 单 IP 子网直接返回
  }

  // 生成随机 IP
  const randomIp = Math.floor(Math.random() * (endIp - startIp + 1)) + startIp;

  return {
    givenIp: ip, // 输入的 IP
    randomIp: intToIp(randomIp), // 同一子网的随机 IP
    mask: mask, // 同一子网的随机 IP
  };
}